#include "topsail.h"
#include "config.h"
#include "wraps.h"

static void set_key_value(struct PNode *p, char *line);
static char *str_trim(char *pStr);
static char *str_trim_quote(char *pStr);

static char buf[MAXLEN];

Config *config_create(char *file)
{	
	Config *config = Malloc(sizeof(Config), __FILE__, __LINE__);
	config->file = Malloc(strlen(file) + 1, __FILE__, __LINE__);
	strcpy(config->file, file);

	struct PNode *pre = NULL;
	struct PNode *p = NULL;

	FILE *fp;
	if ( (fp = fopen(file, "r")) == NULL)
		goto ERR;
	
	while (fgets(buf, sizeof(buf), fp) != NULL) {
		/* ignore comment and blank lines */
		if (!isalpha(buf[0]))
			continue;

		p = Malloc(sizeof(struct PNode), __FILE__, __LINE__);
		set_key_value(p, buf);
		p->next = NULL;

		if (config->first == NULL) /* is the first PNode */
			config->first = p;
		else 
			pre->next = p;

		pre = p;
	}

	Fclose(fp, __FILE__, __LINE__);
	return config;
ERR:
	free(config->file);
	free(config);
	return NULL;
}

void config_destroy(Config *config)
{
	struct PNode *pre = (config == NULL) ? NULL : config->first;
	struct PNode *p = pre;

	while (p != NULL) {
		p = p->next;
		free(pre->key);
		free(pre->value);
		free(pre);
		pre = p;
	}
	free(config->file);
	free(config);
}

void config_list(Config *config)
{
	if (config == NULL)
		return;

	fprintf(stdout, "file: %s\n", config->file);
	struct PNode *p	= config->first;
	int i = 1;
	while (p != NULL) {
		fprintf(stdout, "%d ", i++);
		fprintf(stdout, "key: %s", p->key);
		fprintf(stdout, "\t value: %s\n", p->value);
		p = p->next;
	}
}


char *config_get_value(Config *config, char *key)
{
	struct PNode *p;
	if (config == NULL)
		return NULL;
	
	p = config->first;
	while (p != NULL) {
		if (strcmp(p->key, key) == 0)
			return p->value;
		p = p->next;
	}	
	return NULL;
}

int config_update_value(Config *config, char *key, char *value)
{
	if (config == NULL)
		return -1;
	
	struct PNode *p = config->first;
	struct PNode *pre = NULL;

	while (p != NULL) {
		if (strcmp(p->key, key) == 0) {
			free(p->value);
			p->value = Malloc(strlen(value) + 1, __FILE__, __LINE__);
			strcpy(p->value, value);
			return 0;
		}
		pre = p;
		p = p->next;
	}

	struct PNode *new = Malloc(sizeof(struct PNode), __FILE__, __LINE__);
	new->key = Malloc(strlen(key) + 1, __FILE__, __LINE__);
	strcpy(new->key, key);
	new->value = Malloc(strlen(value) + 1, __FILE__, __LINE__);
	strcpy(new->value, value);
	new->next = NULL;

	if (pre== NULL)	config->first = new;
	else pre->next = new;

	return 0;
}

void config_save(Config *config)
{
	if (config == NULL)
		return;
	
	char tmpfile[1024];
	sprintf(tmpfile, "%s-%d", config->file, getpid());
	
	FILE *fp = Fopen(tmpfile, "w", __FILE__, __LINE__);
	
	char buf[1024];
	struct PNode *p;
	for (p = config->first; p != NULL; p = p->next) {
		sprintf(buf, "%s=\"%s\"\n", p->key, p->value);
		fputs(buf, fp);		
	}
	Fclose(fp, __FILE__, __LINE__);
	Rename(tmpfile, config->file, __FILE__, __LINE__);
}

static void set_key_value(struct PNode *p, char *line)
{
	char *p_equal = strchr(line, '=');
	*p_equal = '\0';

	char *s = str_trim(line);
	p->key = Malloc(strlen(s) + 1, __FILE__, __LINE__);
	strcpy(p->key, s);

	s = str_trim(p_equal + 1);
	s = str_trim_quote(s);
	p->value = Malloc(strlen(s) + 1, __FILE__, __LINE__);
	strcpy(p->value, s);
}

static char *str_trim(char *pStr)
{
    char *pStart = pStr;
    char *pEnd = pStart + strlen(pStart) - 1;

    while(isspace(*pStart)) pStart++;
    while(isspace(*pEnd))   pEnd--;

    *(pEnd + 1) = '\0';
	return pStart;
}

static char *str_trim_quote(char *pStr)
{
	char *pStart = pStr;
	char *pEnd = pStart + strlen(pStart) - 1;
	if (*pStart == '"')	pStart++;
	if (*pEnd == '"')	pEnd--;
	*(pEnd + 1) = '\0';
	return pStart;
}

